/*!
   \file

   © 2011 Mark W. Gabby II

   This file is part of the Avion engine.

   The Avion engine is free software: you can redistribute it and/or modify it under the terms of
   the GNU General Public License as published by the Free Software Foundation, either version 3 of
   the License, or (at your option) any later version.

   The Avion engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with the Avion Engine.
   If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <string>
#include <vector>

#include "Util/typedefs.hpp"
#include "Math/VectorN.hpp"
#include "Components/gcConstants.hpp"

struct FT_LibraryRec_;
typedef struct FT_LibraryRec_ * FT_Library;

static uint32_t const kNumFontStyleTypes = 8;

/*!
    \brief
    The font class abstracts all the different font list
    bases and font initial loading.
*/
class Font
{
public:
   Font();

   bool Load( std::string & FontName, const std::string & FontFileName, const FT_Library & FreeTypeLibrary );
   uint32_t GetStyleListBase( const uint32_t StyleFlags = kFontStyle::Regular ) const;
   float GetBasePercentOfScreenHeight()
   {
      return basePercentOfScreenHeight;
   }
   float GetDiffFromDesiredSize( float PercentOfScreenHeight );
   float GetScalingToSize( const float PercentOfScreenHeight ) const;
   float GetScaledLineGap( float PercentOfScreenHeight );
   float GetScaledLineGapHeight( float PercentOfScreenHeight );

   float CalculateStringWidth( const std::string & String, const float PercentOfScreenHeight, const uint32_t StyleFlags = kFontStyle::Regular ) const;
   float CalculateSubstringWidth( const std::string & String, const uint32_t Offset, const uint32_t NumChars, const float PercentOfScreenHeight, const uint32_t StyleFlags = kFontStyle::Regular ) const;
   float CalculateStringHeightFromBaseline( const std::string & String, const float FontSizePercentOfScreenHeight, const uint32_t StyleFlags = kFontStyle::Regular ) const;
   float CalculateStringDepthBelowBaseline( const std::string & String, const float FontSizePercentOfScreenHeight, const uint32_t StyleFlags = kFontStyle::Regular ) const;
   float CalculateStringRawHeight( const std::string & String, const float FontSizePercentOfScreenHeight, const uint32_t StyleFlags ) const;
   float CalculateStringLeftOffset( const std::string & String, const float FontSizePercentOfScreenHeight, const uint32_t StyleFlags ) const;

   const float CalculateStringPercentToMatchHeight( const std::string & String, const float HeightScreenUnits, const uint32_t StyleFlags ) const;
   const float CalculateStringScaleToMatchWidth( const std::string & String, const float PercentOfScreenHeight,
         const float WidthScreenUnits, const uint32_t StyleFlags ) const;
   const Vector2 CalculateStringDrawOffset( const std::string & String, const float PercentOfScreenHeight,
         const float WidthScreenUnits, const uint32_t StyleFlags ) const;
   void Deallocate();
   ~Font();

private:
   void AllocateDataStorage( const uint32_t StartChar, const uint32_t NumGlyphs );
   bool LoadAllStyles( std::string & FontFilePath, const int32_t HeightPixels, const FT_Library & FreeTypeLibrary );
   // Font Functions
   bool GenerateFontList( const std::string & FontFilePath, const FT_Library & FreeTypeLibrary,
                          const uint32_t HeightPixels, const uint32_t StyleFlags );

   // For each font style there is a list base
   uint32_t listStarts[kNumFontStyleTypes];
   // For each font style, there are a list of texture objects ( per-glyph )
   uint32_t * textureObjectNames[kNumFontStyleTypes];

   // For each font style, there's an array of glyph widths
   // These are in screen units
   float * glyphOriginsToRightExtents[kNumFontStyleTypes];
   float * glyphOriginsToLeftExtents[kNumFontStyleTypes];
   float * glyphAdvances[kNumFontStyleTypes];
   // Distance above baseline
   float * glyphHeightsFromBaseline[kNumFontStyleTypes];
   // Distance below baseline
   float * glyphDepthsBelowBaseline[kNumFontStyleTypes];

   float lowestDistBelowBaseline;
   float lineGap;
   float basePercentOfScreenHeight;
   uint32_t startChar;
   uint32_t numGlyphs;
};
